﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace BYFW.BOL
{
    /// <summary>
    /// 配置型对象基类，包含code属性的对象的基类
    /// 用于系统固定配置对象，如学校的课程列表
    /// 或含上述属性的非海量数据的记录型对象，如公司的项目、合同列表等
    /// 
    /// 当对象不含有code列时，可以在构造函数中设置m_hasCode为false，
    /// 此时本类相当于BaseEntity，但当调用使用code及codeField的方法时会出错【TODO：主动抛出异常信息】，
    /// 目的是使其他派生的基类可以满足有无code情况下都只需从本类继承
    /// </summary>
    [Serializable]
    public class BaseConfigEntity : BaseEntity
    {
        public BaseConfigEntity()
        {

        }

        #region 变量

        /// <summary>
        /// 表示代号字段，可在实体派生类的构造函数中赋值，对应到具体的数据库表
        /// </summary>
        protected string m_codeField = "code";

        /// <summary>
        /// 是否含有code列，可在实体派生类的构造函数中赋值
        /// </summary>
        protected bool m_hasCode = false;

        #region 简单成员变量

        /// <summary>
        /// 代号字段值
        /// </summary>
        protected string m_code = "";

        #endregion

        #endregion

        #region 属性

        /// <summary>
        /// 获取或设置代号code【唯一】
        /// </summary>
        public string Code
        {
            get
            {
                if (!m_hasCode)
                {
                    throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeNotAllowedErr, Language, this.GetType().ToString()));
                }
                return this.m_code;
            }
            set
            {
                if (!m_hasCode)
                {
                    throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeNotAllowedErr, Language, this.GetType().ToString()));
                }
                this.m_code = value;
            }
        }

        /// <summary>
        /// 获得本实例的key，当Code可用时，使用Code作为key
        /// </summary>
        public override object Key
        {
            get
            {
                if (!m_hasCode)
                {
                    return base.Key;
                }
                else
                {
                    return m_code;
                }
            }
        }

        #endregion

        #region 方法

        #region 重载方法

        protected override void FillContainer()
        {
            base.FillContainer();
            if (this.m_hasCode)
            {
                this.m_container.Add(this.m_codeField, this.m_code);
            }
        }
        public override bool GetProperties(DataRow record)
        {
            if (!base.GetProperties(record))
            {
                return false;
            }
            if (this.m_hasCode)
            {
                this.m_code = this.GetStringValue(record, this.m_codeField);
            }
            return true;
        }
        public override void Init()
        {
            if (!m_hasCode)
            {
                base.Init();
            }
            else
            {
                this.GetProperties(m_code);
            }
        }
        public override int Add(string transID)
        {
            lock (this.GetType())
            {
                if (m_hasCode)
                {
                    //没有输入code值
                    if (m_code.Trim() == "")
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeIsEmptyErr, Language, this.GetType().ToString()));
                    }
                    //code值在数据库中已存在
                    if (!this.CanUpdate(transID))
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeExistErr, Language, this.GetType().ToString()));
                    }
                }
                return base.Add(transID);
            }
        }
        /// <summary>
        /// 根据code，将实例成员值更新到数据库，用于事务中
        /// </summary>
        /// <param name="transID">事务ID:为""或null时表示非事务</param>
        public override int Update(string transID)
        {
            lock (this.GetType())
            {
                if (m_hasCode)
                {
                    //没有输入code值
                    if (this.m_code.Trim() == "")
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeIsEmptyErr, Language, this.GetType().ToString()));
                    }
                    //更新后的code值在数据库中已存在
                    if (!this.CanUpdate(transID))
                    {
                        throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeExistErr, Language, this.GetType().ToString()));
                    }
                }
                return base.Update(transID);
            }
        }
        /// <summary>
        /// 根据code，删除本实例的数据记录，用于事务中
        /// </summary>
        /// <param name="transID">事务ID:为""或null时表示非事务</param>
        public override int Delete(string transID)
        {
            if (m_hasCode)
            {
                m_objCacheManager.RemoveObject(this.Key);
                return this.DeleteRecord(transID, this.GetCodeConditionExpression(m_code), false);
            }
            else
            {
                return base.Delete(transID);
            }
        }

        #endregion

        #region 内部辅助方法

        /// <summary>
        /// 获得以code为条件的sql条件语句，
        /// </summary>
        /// <returns></returns>
        protected string GetCodeConditionExpression(string code)
        {
            if (!m_hasCode)
            {
                throw new BaseCustomException(LanguageResource.GetInfo(LanguageResource.EX_BOL_CodeNotAllowedErr, Language, this.GetType().ToString()));
            }
            string condition = string.Format(" WHERE {0}={1}", DB.GetCol(m_codeField), DB.GetVal(code));
            return condition;
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 由指定的code获得本实例的成员属性值，用于事务中
        /// </summary>        
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <param name="code">code列值</param>
        /// <returns></returns>
        public void GetProperties(string transID, string code)
        {
            this.GetProperties(this.GetRecordByCode(transID, code));
        }
        /// <summary>
        /// 由指定的code获得本实例的成员属性值
        /// </summary>
        /// <param name="code">code列值</param>
        /// <returns></returns>
        public void GetProperties(string code)
        {
            bool needCache = false;
            DataRow dr = m_objCacheManager.GetObject(code);
            if (dr == null)
            {
                needCache = true;
                dr = this.GetRecordByCode(code);
            }
            this.GetProperties(dr);
            if (needCache && this.ID > 0)
            {
                m_objCacheManager.AddObject(this.Key, dr);
            }
        }
        /// <summary>
        /// 根据code，判断本实例是否可以进行记录更新
        /// 当code不可用时，始终返回true
        /// </summary>
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <returns></returns>
        public bool CanUpdate(string transID)
        {
            string condition = string.Format(
                "WHERE {0}={1} AND {2}<>{3}"
                , DB.GetCol(m_codeField), DB.GetVal(m_code)
                , DB.GetCol(m_idField), DB.GetVal(m_id));

            if (m_hasCode)
            {
                return !this.Exist(transID, condition, false);
            }
            else
            {
                return true;
            }
        }

        #endregion

        #region 全局方法

        /// <summary>
        /// 删除指定Code的记录，不级联删除
        /// </summary>
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <param name="code">code值</param>
        public void Delete(string transID, string code)
        {
            this.DeleteRecord(transID, this.GetCodeConditionExpression(code));
        }
        /// <summary>
        /// 判断是否存在指定的简单条件的记录，用于事务中
        /// </summary>
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <param name="code">code列值</param>
        /// <returns></returns>
        public bool ExistByCode(string transID, string code)
        {
            string condition = this.GetCodeConditionExpression(code);
            return this.Exist(transID, condition, true);
        }
        /// <summary>
        /// 由指定的code，判断数据库中是否存在本实例
        /// </summary>
        /// <param name="code">code列值</param>
        public bool Exist(string code)
        {
            return this.ExistByCode(null, code);
        }
        /// <summary>
        /// 由指定的code获得一行记录，没有则返回null，用于事务中
        /// </summary>
        /// <param name="transID">事务id，若在非事务中使用，则设置为null</param>
        /// <param name="code">code列值</param>
        /// <returns></returns>
        public DataRow GetRecordByCode(string transID, string code)
        {
            if ((transID == null || transID.Trim() == "") && m_tblCacheManager.IsEnable)
            {
                DataTable dt = this.GetCacheTable();
                DataRow[] drs = dt.Select(DB.GetSimpleCondition(this.GetCodeConditionExpression(code)));
                if (drs.Length > 0)
                {
                    return drs[0];
                }
            }
            else
            {
                DataTable dt = this.GetRecords(transID, this.GetCodeConditionExpression(code));
                if (dt.Rows.Count > 0)
                {
                    return dt.Rows[0];
                }
            }
            return null;
        }
        /// <summary>
        /// 由指定的code获得一行记录，没有则返回null
        /// </summary>
        /// <param name="code">code值</param>
        /// <returns></returns>
        public DataRow GetRecordByCode(string code)
        {
            return this.GetRecordByCode(null, code);
        }

        #endregion

        #endregion

    }
}
